import { CustomStrategy, PassportStrategy } from '@midwayjs/passport';
import { Strategy, ExtractJwt } from 'passport-jwt';
import { Config, Inject } from '@midwayjs/core';
import { InjectEntityModel } from '@midwayjs/typeorm';
import { Repository } from 'typeorm';

import { User } from '../entity/user.entity';
import { RedisService } from '@midwayjs/redis';
import { JwtService } from '@midwayjs/jwt';
import { UnauthorizedError } from '@midwayjs/core/dist/error/http';

@CustomStrategy()
export class JwtStrategy extends PassportStrategy(Strategy, 'jwt') {
  @InjectEntityModel(User)
  userModel: Repository<User>;

  @Inject()
  redisService: RedisService;

  @Config('jwt')
  jwtConfig;

  @Inject()
  jwt: JwtService;

  serializeUser(user, done) {
    // 可以只保存用户名
    done(null, user.username);
  }

  async deserializeUser(id, done) {
    // 这里不是异步方法，你可以从其他地方根据用户名，反查用户数据。
    const user = await this.userModel.findOneBy({ id: id });

    done(null, user);
  }

  // 关键点：使用 getStrategyOptions 获取动态配置
  getStrategyOptions() {
    return {
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      secretOrKey: this.jwtConfig.secret, // 从配置中读取 secret
      ignoreExpiration: false,
      session: false
    };
  }

  async validate(payload: any) {
    // 根据 payload 查询用户是否存在
    const result = await this.redisService.get(`userToken:${payload.uid}`);
    const user = await this.userModel.findOneBy({ id: payload.uid, username: payload.userName });
    if (!user) {
      throw new Error('用户不存在');
    }
    const jwtObj: any = await this.jwt.decode(result)
    if (jwtObj?.uid === payload?.uid && jwtObj?.userName === payload?.userName && jwtObj?.exp === payload?.exp) {
      return payload;
    }
    throw new UnauthorizedError('token已过期,请重新登录');
  }
}